﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ANZ_AIM_GUI.Utils;
using System.Text.RegularExpressions;
using ANZ_AIM_FRAMEWORK;
using ANZ_AIM_BLL;
using ANZ_AIM_BLL.Model;
using log4net;

namespace ANZ_AIM_GUI
{
    public partial class frmChangePassword : Form
    {
        //log4net
        private static readonly ILog logger = LogManager.GetLogger(typeof(frmChangePassword));

        AppParam param = AppParam.Instance;

        public const int CHANGEPWD_OK = 1;
        public const int CHANGEPWD_FAILED_WRONG_PASSWORD = -1;
        public const int CHANGEPWD_FAILED_USER_NOT_FOUND = -2;
        public const int CHANGEPWD_FAILED_MATCH_OLD_PASSWORD = -3;
        public const int CHANGEPWD_FAILED_MATCH_PREVIOUS_PASSWORD = -4;

        public frmChangePassword()
        {
            InitializeComponent();
            this.btnOK.DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(this.txtOldPassword.Text))
                {
                    MessageBox.Show("Please input your current password.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }

                if (string.IsNullOrEmpty(this.txtNewPassword.Text))
                {
                    MessageBox.Show("Please input your new password.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }

                if (string.IsNullOrEmpty(this.txtNewPasswordConfirm.Text))
                {
                    MessageBox.Show("Please input confirm password.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }

                if (string.IsNullOrEmpty(this.txtOldPassword.Text) ||
                    string.IsNullOrEmpty(this.txtNewPassword.Text) ||
                    string.IsNullOrEmpty(this.txtNewPasswordConfirm.Text))
                {
                    MessageBox.Show(Constant.SYS_MSG_VALID_ALL_REQUIRED, Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }
                else if (!IsStrongPassword(txtNewPassword.Text))
                {
                    string message =
                        "Invalid password." + System.Environment.NewLine +
                        "Please enter a new password that" + System.Environment.NewLine +
                        "- Has at least 8 characters" + System.Environment.NewLine +
                        "- Has at least 1 alpha character" + System.Environment.NewLine +
                        "- Has at least 1 numeric character" + System.Environment.NewLine +
                        "- Has at least 1 capital letter" + System.Environment.NewLine +
                        "- Has at least 1 special character";

                    MessageBox.Show(message, Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }
                else if (txtNewPassword.Text != txtNewPasswordConfirm.Text)
                {
                    MessageBox.Show("New Password and Confirm Password are not matched.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.DialogResult = DialogResult.None;
                    return;
                }

                switch (ChangePwdClicked())
                {
                    case CHANGEPWD_FAILED_MATCH_OLD_PASSWORD:
                        MessageBox.Show("The New Password is the same as Current Password. Please use another.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        this.DialogResult = DialogResult.None;
                        break;
                    case CHANGEPWD_FAILED_MATCH_PREVIOUS_PASSWORD:
                        MessageBox.Show("New password must be different from 3 previous passwords.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        this.DialogResult = DialogResult.None;
                        break;
                    case CHANGEPWD_FAILED_WRONG_PASSWORD:
                        MessageBox.Show("The current password is incorrect.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        this.DialogResult = DialogResult.None;
                        break;
                    case CHANGEPWD_FAILED_USER_NOT_FOUND:
                        MessageBox.Show("Current user not found.", Constant.SYS_ERROR, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        this.DialogResult = DialogResult.None;
                        break;
                    case CHANGEPWD_OK:
                        MessageBox.Show("Password is changed successfully.", Constant.SYS_INFORMATION, MessageBoxButtons.OK, MessageBoxIcon.Information);
                        this.Dispose();
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.InnerException == null ? ex.Message : ex.InnerException.Message, Constant.SYS_ERROR, MessageBoxButtons.OK);
                logger.Error(ex.Message + " - " + ex.StackTrace);
            }
        }

        private bool IsStrongPassword(string password)
        {
            bool result = false;

            /* Regular expression pattern for a strong password:
             * - Has at least 8 characters
             * - Has at least 1 alpha character
             * - Has at least 1 numeric character
             * - Has at least 1 capital letter
             * - Has no special character
             * Source: http://stackoverflow.com/questions/3131025/strong-password-regex
             */
            //string pattern = "(?=.*[A-Z])(?=.*\\d)[a-zA-Z0-9]{8,}$";
            string pattern = "(?=.*\\p{Lu})(?=.*\\p{Ll})(?=.*\\d)(?=.*[^\\p{L}\\d]).{8,}$";
            if (Regex.IsMatch(password, pattern, RegexOptions.None))
                result = true;

            return result;
        }

        public int ChangePwdClicked()
        {
            try
            {
                // encrypt current password
                string currentPassword = txtOldPassword.Text;
                AESHelper aes = new AESHelper();
                currentPassword = aes.EncryptToString(currentPassword);

                UserBLL userBll = new UserBLL();
                User user = userBll.GetById(param.UserId);
                if (user != null)
                {
                    if (user.Password != currentPassword)
                    {
                        return CHANGEPWD_FAILED_WRONG_PASSWORD;
                    }

                    // encrypt new password
                    string newPassword = txtNewPassword.Text;
                    newPassword = aes.EncryptToString(newPassword);

                    if (currentPassword == newPassword)
                    {
                        return CHANGEPWD_FAILED_MATCH_OLD_PASSWORD;
                    }

                    if (user.PwdArray != null && !string.IsNullOrEmpty(user.PwdArray.Trim()) && (user.PwdArray.Split(',').Any(t => t == newPassword)))
                    {
                        return CHANGEPWD_FAILED_MATCH_PREVIOUS_PASSWORD;
                    }

                    user.Password = newPassword;
                    user.MustChangePwd = "N";
                    user.LastChangedPwd = MiscHelper.DateTimeToShort(DateTime.Now);


                    if (user.PwdArray == null || string.IsNullOrEmpty(user.PwdArray.Trim()))
                    {
                        // Store 3 passwords
                        user.PwdArray = currentPassword + "," + user.Password + ",";
                    }
                    else
                    {
                        string[] passArr = user.PwdArray.Split(',');
                        // Find current password in array
                        for (int i = 0; i < passArr.Length; i++)
                        {
                            if (passArr[i] == currentPassword)
                            {
                                if (i == passArr.Length - 1)
                                {
                                    passArr[0] = user.Password;
                                    break;
                                }
                                else
                                {
                                    passArr[i + 1] = user.Password;
                                    break;
                                }
                            }
                        }

                        // Rebuild password array
                        user.PwdArray = string.Empty;
                        for (int i = 0; i < passArr.Length; i++)
                        {
                            user.PwdArray += passArr[i] + ',';
                        }
                        user.PwdArray = user.PwdArray.TrimEnd(',');
                    }

                    userBll.Save(user);
                    return CHANGEPWD_OK;
                }
                else
                {
                    return CHANGEPWD_FAILED_USER_NOT_FOUND;
                }

            }
            catch (Exception ex) { throw ex; }
        }
    }
}
